//
//  Pai_TextView.swift
//  CharPI
//
//  Created by 青色石头 on 2019/12/16.
//  Copyright © 2019 青色石头. All rights reserved.
//

import UIKit

class Pai_TextView: UITextView {
    
    var textDidChangedClosure: ((_ textView: Pai_TextView)->Void)?
    
    var textDidEndEditingClosure: ((_ textView: Pai_TextView)->Void)?
    
    var textDidMaxLengthClosure: (()->Void)?
    
    var maxLength = UInt.max
    
    var placeholder: String? {
        didSet {
            placeholderLabel.text = placeholder
            refreshPlaceholder()
        }
    }
    
    var placeholderColor: UIColor {
        didSet {
            placeholderLabel.textColor = placeholderColor
            refreshPlaceholder()
        }
    }
    
    private let placeholderLabel = { () -> UILabel in
        let lbl = UILabel(frame: CGRect.zero)
        lbl.numberOfLines = 0
        lbl.translatesAutoresizingMaskIntoConstraints = false
        return lbl
    }()
    
    
    var formatText: String {
        get {
            return text.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
        }
    }
    
    
    required init?(coder aDecoder: NSCoder) {
        placeholderColor = UIColor.black
        super.init(coder: aDecoder)
        addSubview(placeholderLabel)
    }
    
    private override init(frame: CGRect, textContainer: NSTextContainer?) {
        placeholderColor = UIColor.black
        super.init(frame: frame, textContainer: textContainer)
        addSubview(placeholderLabel)
    }
    
    class func textView() -> Pai_TextView {
        let textView = Pai_TextView(frame: CGRect.zero, textContainer: nil)
        return textView
    }
    
    deinit {
        NotificationCenter.default.removeObserver(self)
        textDidChangedClosure = nil
        textDidMaxLengthClosure = nil
    }
    
}
// MARK: - overwrite
extension Pai_TextView {
    
    override var text: String! {
        didSet {
            refreshPlaceholder()
        }
    }
    override var attributedText: NSAttributedString! {
        didSet {
            refreshPlaceholder()
        }
    }
    override var font: UIFont? {
        didSet {
            placeholderLabel.font = font
            setNeedsLayout()
            layoutIfNeeded()
        }
    }
    override var textAlignment: NSTextAlignment {
        didSet {
            placeholderLabel.textAlignment = textAlignment
        }
    }
    
    override func becomeFirstResponder() -> Bool {
        NotificationCenter.default.addObserver(self, selector: #selector(Pai_TextView.textDidChanged(notification:)), name: UITextView.textDidChangeNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(Pai_TextView.textDidEndEditing(notification:)), name: UITextView.textDidEndEditingNotification, object: nil)
        return super.becomeFirstResponder()
    }
    
    override func resignFirstResponder() -> Bool {
        let bool = super.resignFirstResponder()
        NotificationCenter.default.removeObserver(self, name: UITextView.textDidChangeNotification, object: nil)
        NotificationCenter.default.removeObserver(self, name: UITextView.textDidEndEditingNotification, object: nil)
        return bool
    }
    
    override var intrinsicContentSize: CGSize {
        if self.hasText {
            return super.intrinsicContentSize
        }
        
        let pholderInsets = placeholderInsets();
        var newSize = super.intrinsicContentSize
        newSize.height = placeholderExpectedFrame().size.height + pholderInsets.top + pholderInsets.bottom;
        return newSize;
    }
    
//    override func caretRect(for position: UITextPosition) -> CGRect {
//        var rect = super.caretRect(for: position)
//        // 这里有问题，只要取一行的高度就行了。暂时先注释掉
//        let nHeight = placeholderExpectedFrame().size.height
//        rect.size.height = nHeight
//        return rect
//    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        self.placeholderLabel.frame = placeholderExpectedFrame()
    }
    
    @objc private func textDidEndEditing(notification: Notification) {
        textDidEndEditingClosure?(self)
    }
    
    @objc private func textDidChanged(notification: Notification) {
        guard (notification.object as? Pai_TextView) != nil else {
            return
        }
        placeholderLabel.isHidden = self.text.count > 0
        
        if text.count == 1 {
            if text == " " || text == "\n" {
                text = ""
            }
        }
        
        if maxLength != UInt.max && maxLength != 0 && text.count > 0 {
            if markedTextRange == nil && text.count > maxLength {
                if let textDidMaxLengthHandle = textDidMaxLengthClosure {
                    textDidMaxLengthHandle()
                    text = String(text.prefix(Int(maxLength)))
                }
            }
        }
        
        if let textDidChangedHandle = textDidChangedClosure {
            textDidChangedHandle(self)
        }
    }
}

// MARK: - config
extension Pai_TextView {
    
    private func refreshPlaceholder() {
        if text.count != 0 || attributedText.length != 0 {
            placeholderLabel.alpha = 0
        }else {
            placeholderLabel.alpha = 1
        }
        setNeedsLayout()
        layoutIfNeeded()
    }
    
    private func placeholderInsets() -> UIEdgeInsets {
        return UIEdgeInsets(top: self.textContainerInset.top, left: self.textContainerInset.left + self.textContainer.lineFragmentPadding, bottom: self.textContainerInset.bottom, right: self.textContainerInset.right + self.textContainer.lineFragmentPadding)
    }
    
    private func placeholderExpectedFrame() -> CGRect {
        let pholderinsets = placeholderInsets()
        let maxWidth = self.frame.width - pholderinsets.left - pholderinsets.right
        let expectedSize = placeholderLabel.sizeThatFits(CGSize(width: maxWidth, height: frame.height - pholderinsets.top - pholderinsets.bottom))
        return CGRect(x: pholderinsets.left, y: pholderinsets.top, width: maxWidth, height: expectedSize.height)
    }
}
